perm filename WCCF.1[P,JRA] blob sn#554872 filedate 1981-01-09 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00002 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	.HLINES←  68 	<< 49 NUMBER OF LINES/PAGE >>
C00050 ENDMK
C⊗;
.HLINES←  68 	<< 49 NUMBER OF LINES/PAGE >>
.WCHARS←  48 	<< 81 NUMBER OF CHARS/LINE >>

.turn on "↓#"

.
.
.PAGE FRAME HLINES+2 HIGH WCHARS WIDE 
.AREA TEXTER LINES 1 TO HLINES CHARS 1 TO WCHARS 
.PLACE TEXTER 

.begin verbatim





			 THE BANKRUPTCY OF BASIC

			      John R. Allen

	     The LISP Company Box 487, Redwood Estates 95044
.end


I predict  that  the  current  trends  utilizing
programming languages like BASIC at the  expense
of abstraction will have a serious impact on the
creativity of the next generation of high school
and and college graduates.

I surmise that the  New Mathematics program  met
resistance  because  it  was  too  abstract  and
short-changed intuition.

I believe that computer science has now  matured
to the extent that it can offer an  intermediate
position to the two  above extremes.  I  believe
that this position --based on a few  fundamental
principles of  computation--  can  be  developed
into a  viable and  exciting program  that  will
teach the  substance  of computing  rather  than
dwelling on  the  form of  specific  programming
languages.  These  fundamentals  of  computation
are  easier  to  present  and  understand   than
contemporary programming languages due to  their
pre-occupation with syntax and shortsighted view
of data structures.


The approach  I  am  advocating is  based  on  a
notation/language named  LISP whose  foundations
are  based   on   mathematical   principles   as
well-founded as those of sets and functions, yet
whose programs can  be executed  by a  computer.
Furthermore from a practical standpoint, LISP is
the language  most commonly  used in  Artificial
Intelligence work; these AI applications and the
techniques they embody offer an incredibly  rich
source  of   examples  and   insight  into   the
non-mathematical aspects of computing.


LISP,  with  its   dual  role  as   mathematical
formalism  and  advanced  programming  language,
offers unique  opportunities  to those  who  are
first encountering computing. The point of  this
note is to sketch some of those benefits, and in
the process  show  how  a  language  like  BASIC
shortchanges one's view of computing.


Consider the following quote:

"... it is  important not to  lose sight of  the
fact that there is a difference between training
and  education.   If  computer   science  is   a
fundamental    discipline,    then    university
education  in   this  field   should   emphasize
enduring  fundamental  principles  rather   than
transient current technology."

Peter Wegner Three Computer Cultures, 1970.


The "Three Cultures" referred  to in this  quote
are:  Computer   Mathematics  (applications   in
traditional  mathematics  that  can   profitably
apply  computers);   Computer  Technology   (the
engineering and physical aspects surrounding the
realization of computing devices), and  Computer
Science (the study of computing). It is a useful
separation  of   the  scientific   aspects   and
ramifications of computers.

Computer Technology  is well  understood in  the
Silicon Valley; it this  the art and science  of
building the physical  devices: applied  physics
and engineering.   Computer Mathematics  is  the
art  and   science  of   using  the   tools   in
mathematics:   applied  mathematics.    Computer
Science? It  is the  study of  computation,  and
programming is applied computation!

Returning to  the  body of  the  quotation,  the
necessity to emphasize "fundamental  principles"
is  not   the   sole   responsibility   of   the
universities.  Many of  one's educational  goals
and expectations are established in high school;
it  is  therefore  most  important  that   one's
introduction to any  subject be  as faithful  to
that  discipline  as  teaching  and   technology
allow. Most subject areas have a  well-developed
historical  perspective   that  supports   their
curricula.  Computer  science  is  a  relatively
young field in the technological domain, but its
roots are well-founded in mathematics.

One objective  of this  note is  to  demonstrate
that  an   appropriate  blend   of   traditional
mathematics and  foundational  computing  offers
substantial advantages  for both  programs.  One
concern I have with the current approach is that
both programs may suffer; mathematics may become
(even more) equated with "deep, but irrelevant",
and computing be  equated with  "shallow, but  a
good career". Mathematics  programs have had  to
deal with this phenomenon for years  --dwindling
enrollments in University  programs are  common.
The phenomenon  has even  more drastic  economic
potential in the computing field:  an oft-quoted
statistic for  the useful  lifetime of  computer
science knowledge  is  five  years!  Surely  the
result of teaching technology, not fundamentals.
The result is stagnant engineering or  expensive
retraining to  keep  up.   No  wonder  one  sees
editorials and articles decrying the diminishing
productivity rate in our computing field,  while
pointing  to  Japan's   and  Europe's   superior
performance. Both the French and Japanese have a
strong interest in  foundational computing.   It
is time to turn  things around in this  country,
and the place to begin is in the high schools.

My comments apply  both to  courses that  expect
their attendees to go on to university education
and it applies to programs that are to give  the
general  populace  an   understanding  of   what
computing is  about and  how it  will impact  on
their lives: the important area called "computer
literacy."    In    neither    case    will    a
technology-driven curricula  suffice;  the  next
five  years  will   see  inexpensive   computing
systems  with  the  power  of  today's  research
machines,  tied   together  through   high-speed
networks,   being   accessed   through    highly
interactive   graphical   techniques.    Several
important and innovative  projects are  underway
now to address these issues: the LOGO project at
MIT, the Smalltalk project at Xerox.  A  cursory
knowledge about  how  a computer  works  coupled
with an  introduction  to  BASIC  won't  prepare
people to cope  with these  systems (since  both
systems  are  targeted  as  educational   tools,
perhaps  we   should  expect   to  see   another
"parental backlash" like  that experienced  with
the New Math program).


Further concern is the  effect of inaccurate  or
inadequate information  on  those  who  plan  to
continue in a university.  First, I surmise that
many bright people are put-off by the patch-work
appearance of computing and opt for  disciplines
that show more  substance.  If computer  science
is  to  prosper,   these  individuals  must   be
attracted.  Second,  there are  severe  problems
even for those who  do enter a  computer-related
career. Questions  are  being raised  about  the
"effect of one's first programming language"; it
is a real  concern. The  expressivity and  style
that one develops with their first language  has
long-term  effect.   This  holds   for   natural
language as well as artificial. The lessons that
one  learns  from   BASIC  about  structure   of
algorithms and  data  are hard  to  overcome.  A
colleague of mine  (a professor  at Santa  Clara
University) can give first-hand testimony  about
the difficulties involved in teaching people  to
unlearn  misconceptions  about  computing.   The
department policy has been to use a "structured"
form of Fortran and Pascal as the vehicle.  Both
of these languages support modern techniques for
expressing algorithms.   Those  who  have  BASIC
experience find it difficult to assimilate these
ideas into their programming style while novices
suffer no such handicap.

Please  note:  the  point  is  not  to  teach  a
programming language;  the  point  is  to  teach
about  computing  and,  in  the  process,  teach
people  to  think.   Of  course,  we  need  some
notation for giving precise descriptions of  our
concepts, but the notation should not become the
object of study. Compare:

"Mathematical notation is always introduced  [in
context as needed] rather than being taught,  as
programming  languages   commonly  are,   in   a
separate course. Notation  suited as  a tool  of
thought  in   any  topic   should  permit   easy
introduction in the context of that topic."

Ken Iverson "Notation as a Tool of Thought" 1979
Turing Award Lecture

As  "tools   of   thought",   most   programming
languages  fail  miserably.   Their  design   is
overly constrained by considerations related  to
their execution on contemporary computers; as  a
result they  fall  short in  satisfying  in  the
criteria by which  notations have  traditionally
been judged.

Iverson suggests  that  in the  past,  notations
have succeeded or failed on considerations  like
the following:

Ease  of   expressing  constructs   arising   in
problems

Suggestivity

Ability to subordinate detail

Economy

Amenability to formal proofs

The  first  three  considerations  are  related;
expressions in  the  notation  must  embody  the
problem  statement  in  such  a  way  that   the
intellectual burden in manipulating the notation
is less  than that  involved with  the  informal
conception of the  problem. Manipulation of  the
notation must aid the  solution of the  original
problem as well as support the generalization of
results.


The notion of economy means that one can explain
the principles of the notation from a few  basic
concepts and rules.  For example, number  theory
can be build from  the primitives of the  number
zero,  equality  relation,   the  operation   of
"adding one", and recursion. LISP has a  similar
foundation. Building from the notion of sequence
and equality, with four primitive operations and
recursion one can construct both the theoretical
and the  programming  structures of  LISP.   The
effect is to supply  the learner with a  simple,
easily grasped system that  can be expanded  and
elaborated   as   familiarity   increases.   The
pedagogical benefits  in  such an  approach  are
substantial.

The notion of proof has been a main-stay in  the
history  of  mathematics.   Its  application  in
science  and  parts  of  mathematics  has   been
informal, but  is  always  grounded  on  logical
foundations that would support formal  argument.
A computational  notation must  at least  do  as
well.

To the traditional  notational concerns we  must
add two computer-age ones:

The notation must be executable

The notation  should be  easy for  a machine  to
manipulate

Surely, if the  notation is  to be  usable as  a
programming language it must be implementable on
a machine and the expressions that one writes in
the  notation   must   be   executable   in   an
unambiguous fashion  and must  be computable  in
finite time.

The second point is  overlooked in almost  every
programming language design.   We see  languages
that completely ignore the issue of manipulation
of  programs   (Fortran  and   Algol);  we   see
languages  that   allow  the   manipulation   of
programs as strings (Snobol  and BASIC); we  see
languages that allow  manipulation as  character
arrays (APL).  Yet programs  are none  of  these
objects.  Programs are  structured objects  with
interrelated parts  and  pieces.  Programs  that
manipulate    these    representations     (like
compilers) must  be  able  to  manipulate  these
representations in  meaningful  ways.   To  this
date, LISP is the only notation that supports  a
representation of programs with the  theoretical
benefits  that  allows  mathematical  discussion
while supporting the practical concerns that are
required to write complex programs.


In  summary,   we   must  identify   and   teach
principles of  computation and  in that  context
one must  introduce  a notation.  That  notation
must embody these principles in such a way  that
one can  reason about  statements made  in  that
notation much  like  one  carries  on  sustained
analysis    in     mathematical     disciplines.
Furthermore, that notation must be executable on
a machine in an unambiguous fashion.  We believe
that the underlying  structure of LISP  supplies
such principles.   The  remainder of  this  note
argues this case.


To   begin,   a   useful   distinction   between
mathematics and computer science is: mathematics
stresses "function"  and  and  computer  science
stresses  "algorithm"  --one   can  argue   that
set-theoretic  ideas  are  more  primitive  than
functionality,  but  I  am  not  concerned  with
minimality  arguments.    Regardless  of   one's
starting point, the idea  of "function" is  more
abstract than  the  idea  of  "algorithm".   The
essential  distinction  being  that  a  function
definition gives an (implict or explict) rule of
correspondence  while  an  algorithm  gives   an
explicit computational  method  for  calculating
those correspondences: there are many algorithms
that will compute the same function.  One way to
understand  "functionality"   is   to   view   a
realization of a function as an algorithm.

At the introductory level, moving from  function
to algorithm  can have  substantial benefit.  An
algorithm is  a  concrete recipe  and,  given  a
computer,  one   can  execute   the   algorithm,
reinforcing one's confidence in the process.  It
is important that  introductory concepts have  a
strong intuitive  real-world  component;  later,
one can abstract from  algorithm to function  by
presenting two algorithms that compute the  same
function and explore what that means.


For example, consider  the following example  of
functional notation:

f(x,y) = x*y - 3*x.

When asking "what is  the value of f(1,2)?"   we
note that  it  doesn't  matter  whether  x*y  is
evaluated before  3*x; that  is, f  expresses  a
functional  relationship,   and  any   rule   of
computation    (obeying    certain    precedence
conventions) will  suffice. I  strongly  suspect
that one teaches (and learns) the evaluation  of
such    expressions    algorithmically,     only
abstracting to the functional level much  later,
if ever.

To  motivate  the   function  versus   algorithm
distinction, consider  the  factorial  function,
defined for non-negative integers:

0! = 1

n! = n*(n-1)! if n is greater than 0.

which says, "given a non-negative integer, if it
is zero, the value is 1; otherwise the value  is
that  integer   multiplied  by   the   factorial
function  operating  on  the   integer-minus-1."
or... "given an integer, call it n. If n is zero
the answer expected is 1, otherwise the expected
answer is n multiplied by the factorial function
operating on n-1."

or... combining with functional notation,

.begin verbatim
factorial(n) = if n=0 then 1
		      else n*factorial(n-1)

Now consider:

fun(x,y) = if x=0 then y
		  else fun(x-1,x*y)
.end

take a moment to look  at fun and then  consider
the values of  fun(1,1), fun(2,1) and  fun(3,1),
for example.

Would you like to  conjecture that fun(x,1)  has
the  same  value  as  factorial(x),  for   every
integer x?  How would  you convince  someone  of
that conjecture?  Write  each in  a  programming
notation and  run them  on  a machine  for  many
values of x?  That's certainly a  start: for  if
the conjecture was  false you  might discover  a
mis-match. But that technique is no proof if the
conjecture is true. It requires proof.

Indeed, the equivalence of these definitions can
be proved.  What does this mean? it says we have
two algorithms that  compute the same  function.
The proof technique is essentially  mathematical
induction.  In fact such  proofs are an  elegant
way to  motivate induction,  and a  lot more  of
computing --for the definitions given above  are
called   recursive   definitions,   an   elegant
formalism analogous to our goal/sub-goal problem
solving intuition.

The equations listed above are, in fact, a  form
of  LISP.    In   LISP,   one   uses   recursive
definitions as  programming language  constructs
to  write   elegant  well-structured   programs.
Furthermore, one  can prove  properties of  LISP
programs using mathematically valid  principles.
Finally, one  can combine  the theory  with  the
practice and can write LISP programs that  would
take two definitions  as input,  use the  formal
rules    for    program    manipulation,     and
automatically prove the equivalence of these two
definitions.

It is this last  area, the manipulation of  LISP
programs by  other LISP  programs that  accounts
for much of LISP's power: to be able to  compute
with data one must  represent it in a  computer;
traditionally we  have made  our data  fit  into
numeric  quantities  or  arrays  of  numbers  or
characters.   LISP   frees    us   from    these
restrictions,  allowing  us   to  compute   with
sequences whose elements can be other  sequences
or simply  symbolic names.  Intellectually,  the
shift makes  it  much easier  to  represent  and
manipulate  complex  information;  that  is  the
business   of    Artificial   Intelligence    in
particular, and intelligence in general.

The key to  this flexibility  and liberation  of
thinking was  LISP's  use of  the  sequence  (or
list) as its underlying data representation.  In
LISP, a sequence  is something like  (A, B,  (C,
D)). This sequence has three elements, the third
being a sequence itself.  Since the commas  just
get in the way, we drop them:  (A B (C D)).

For example, to input  the fun algorithm to  our
program-equivalence prover we would write:

.begin verbatim
(DEFINE FUN (X Y)
      (IF (EQ X 0)
	   Y
	  (FUN (MINUS X 1) (TIMES X Y))))
.end


The syntactic transformation from "fun" to "FUN"
is  simple  --essentially  replacing  functional
notations like:
.begin verbatim

f(x, y, g(z))      by     (F X Y (G Z)), but

.end
the transformation is  a powerful  one from  the
perspective of our  prover.  Such programs  must
be able to select, compare, and manipulate  data
structures  that  represent  subexpressions   of
algorithms like "fun".  In the representation, a
subexpression is either an "atomic symbol" or  a
sequence itself; and  any sequence represents  a
functional application, with  the first  element
of the sequence giving  the name of the  applied
function.  Given  this  sequence  representation
and the operations to manipulate sequences,  the
task of  writing complex  programs becomes  much
more manageable.

For   example,    language   processors    (like
interpreters and  compilers)  initially  process
language statements into  an internal  tree-like
representation.  They  do  this  because   these
tree-structures are  an  efficient form  of  the
program for  further processing.   Since  LISP's
sequence notation has  a natural  representation
as a  tree structure  it becomes  quite easy  to
write compilers in LISP.  For example, a  rather
good LISP compiler can be concisely described on
one 8-1/2 x 11 page; can be easily explained and
read; and  can  be proven  correct.   Since  the
transformation is so simple and yet so powerful,
LISP programs are usually expressed directly  in
this sequence  representation  and  executed  in
this form.

Languages that  offer  only  numeric  or  string
objects do not supply sufficient flexibility for
complex processsing of structures; therefore the
programmer     must      create      lower-level
representations   for   the   needed   tree-like
abstractions. The result is a much less readable
and more complex program.

In  BASIC,   this   complexity   permeates   the
programming process.  Consider, for example, the
Towers of  Hanoi  puzzle: given  three  vertical
rods and a stack of  discs on one rod,  arranged
by size such that the largest is on the  bottom;
move the discs to  the adjacent rod, subject  to
the constraints that only one disc may be  moved
at a time, and no disc may be placed on top of a
smaller disc.

Here is a LISP solution.
.begin verbatim
hanoi(n, source, destination, spare) 
  <= if n=1 then move(source, destination)
            else hanoi(n-1, 
		       source, 
	               spare, 
		       destination)
		 move(source, destination)
		 hanoi(n-1, 
		       spare, 
		       destination, 
		       source)
.end
Here is  a BASIC  solution from  the March  1980
issue of BYTE Magazine:

.group skip 46;

.BEGIN VERBATIM

Even translating  the  LISP  solution  into  its
sequence representation,  we still  have a  more
understandable program  than that  displayed  by
BASIC:

(DEFINE HANOI (N SOURCE DESTINATION SPARE)
  (IF (EQ N 1) (MOVE SOURCE DESTINATION)

      (HANOI (SUB1 N) SOURCE SPARE DESTINATION)
      (MOVE SOURCE DESTINATION)
      (HANOI (SUB1 N) SPARE DESTINATION SOURCE)))

with

(DEFINE MOVE (S D)
    (PRINT "Move disk from" S "to" D))

to print the result on the terminal

and a call:

(HANOI 22 "first" "second" third")

to begin execution.
.END

The  solutions  can  be  contrasted  on  several
levels. In  the BASIC  solution, (line  20)  one
must prescribe  the  number of  disks  that  the
program will manipulate;  of course, most  other
programming   languages   also   require    this
declaration.  However,   such   information   is
totally  irrelevant  to  the  description   (and
correctness) of the algorithm; LISP requires  no
such  declarations.   Many  LISP  systems  allow
declarations   to   aid   the   programmer    in
maintaining consistency, and to aid the compiler
when compiling  code,  but the  LISP  definition
will execute quite handily without declarations.

Further criticism can  be raised concerning  the
GOSUB construct.  The  BASIC  program  maintains
that GOSUB 180 is a call on the Hanoi procedure.
That is not at all clear from the text; "180" is
not "Hanoi", and it is  not at all obvious  what
"180"  is  operating  on   as  data.  The   LISP
definition,  with   its  nmeumonic   names   and
explicit  parameters,  makes   it  clear   which
function is  being called  and what  objects  it
operates on.   One  may  also  ponder  what  has
happened to the recursive algorithm when it  was
encoded in the BASIC solution

These last two  issues --  "180" versus  "Hanoi"
and   the   destruction    of   the    recursive
formulation--    exemplify    the    issue    of
"abstraction":  the   abstract,  or   high-level
description of algorithms. The LISP solution  is
more abstract in that it directly expresses  the
relationships between  consecutive steps,  while
not  requiring  unnecessary  specifications   of
implementation details.  Convincing  oneself  of
the correctness  of the  LISP formulation  is  a
much easier task than that of convincing oneself
of the correctness of the BASIC program.


Besides     LISP's     flexible      algorithmic
expressibility, an integral part of LISP's power
derives  from   its   ability  to   define   and
manipulate data abstractly.  This means that one
can write LISP  algorithms that manipulate  data
without regard for the implementation details of
the data.  In LISP one can define and manipulate
"abstract objects". The objects are abstract  in
that they are described  by their behavior,  not
by    their    implementation.    Objects    are
characterized  by  functions  called  "testers",
"selectors", and "constructors". One can test an
object for specified properties; one can  select
components from (appropriately tested)  objects,
and given  a  collection  of  objects,  one  can
create new objects.

These ideas of abstract objects, manipulated  by
algorithms   using   testers,   selectors,   and
constructors,  are  at   the  heart  of   modern
computer science.

Most programming languages have great difficulty
with this  concept  of abstraction.  Either  the
language fails to support an appropriate set  of
component data  types  (Fortran,  Algol,  Basic,
APL) or fails  to support  the interrelating  of
components at  a  high level  (PL/1  and  Pascal
pointers).  The effect  is the  same: one  loses
the    notation    to    the    strictures    of
implementation.


An essential problem stems  from the failure  to
recognize   that   programming   languages   are
essentially notations. As notations, their first
concern  must  be  expressibility  of   thought.
Therefore,  a   high-level  language's   primary
benefit (over  machine language)  is  notational
not computational. The development cycle of most
programming  languages   has  been   driven   by
computational  (implementation)   considerations
rather  than   by   notational   considerations.
Languages  driven  by  implementations   include
Fortran,  Basic,  and  to  some  extent   Algol.
Languages driven by notation include LISP,  APL,
LOGO, and Smalltalk.

So, at one level,  we agree with the  "hands-on"
algorithmic  approach   contained   within   the
computer-oriented  educational  philosophy.  Our
disagreement is not with the instrument, but  in
the way it  is being applied  or "played".   One
objection stems from the emphasis on performance
without an  appropriate view  of the  instrument
itself. The  typical  computing  application  is
exactly   that:   "an   application",   not   an
introduction  to  computing.   The  essence   of
Computing  is  the  study  of  algorithms,   not
applications.  I do  not even advocate  teaching
LISP as a programming  language, per se:  that's
only moving from the  "slide rule" to the  "hand
calculator".

Mechanical techniques, like  the slide rule  (in
mathematics)  and   any   specific   programming
language (in computer science) are inappropriate
vehicles for teaching principles. The slide rule
was only a tool (transient technology), applying
principles   of   mathematics.   A   programming
language is a tool,  applying the principles  of
computing.  It is the fundamental ideas that are
important,  and  those  are  much  more   easily
presented in the  LISP model than  in the  BASIC
model.  As a  "consumer" language,  BASIC is  no
more obnoxious than  Saturday morning  cartoons;
as  a  medium  for  teaching  people  about  the
elegance  of  computing,   it  is  deadly.    It
shortchanges one's  intellect; its  expressivity
and style are extraordinarily primitive. I  fear
we  will  discover  that   we  have  created   a
generation of "consuming  programmers", able  to
read  (execute)  other  people's  programs   but
unable to  write  (create)  effectively  because
they do not understand the principles.

There are several ingredients that contribute to
a  creative  endeavor   besides  an   expressive
language, a  fluent author,  and an  inquisitive
mind. One  must  also have  appropriate  working
conditions.  Though   many   BASIC's   do   have
interactive features, their scope is limited. In
this  area  of  interactive  programming,   LISP
excells.  In  its  role  as  the  implementation
language for  Artificial Intelligence  research,
LISP systems have  acquired an impressive  array
of  program  development  tools.  There  is   an
important practical  lesson  to be  gained  from
using such tools,  much like  the liberation  of
expression   one    feels   on    moving    from
pencil-and-paper to  a  good text  editor.  This
mode of communication with a computer is at  the
heart of the  LOGO/Smalltalk enterprises;  these
tools   aid   substantially   in   making    the
program-creation   process   a   pleasant    and
rewarding experience. The immediate feedback  of
interactive   computing,    coupled   with    an
"economic"  (see  earlier  comments)   notation,
results in a very effective pedagogical tool.

Clearly I  cannot adequately  cover a  topic  as
deep and varied LISP in only a few pages. I have
said little  about the  interactive  development
style and  programming  environments  that  LISP
lends itself to,  and I have  said little  about
the kinds of applications that has made LISP the
major  tool  of  AI.   I  am  preparing  a  more
detailed version of this paper that will address
these issues, however I feel these  foundational
issues  are  the  most   critical.  I  am   most
interested in your reaction  to this draft,  and
hope  some  of  the  ideas  presented  here  are
valuable to you.



Bibliography
1. Iverson, K. "Notation as a Tool of Thought", CACM, August 1980.